﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using Socium.Domain.Collections;
using Vector = Socium.Science.Vector;

namespace Socium.Documents.Sociograms {
	static class Arrow {
		static Vector ToVector(this Point point) {
			return new Vector(point.X, point.Y);
		}

		static Point ToPoint(this Vector vector) {
			return new Point(vector.X, vector.Y);
		}

		public static Geometry GetGeometry(Point start, Point end, ArrowCaps caps, double thickness, Vector cap) {
			var a = start.ToVector();
			var b = end.ToVector();

			var v = (b - a).Normalize();
			var n = v.Perpendicular();

			var w = cap.X - thickness;
			var h = cap.Y / 2d - thickness;

			ICollection<Vector> vectors = new LinkedList<Vector>();
			switch (caps) {
				case ArrowCaps.Start:
					vectors.Add(b);
					AddCap(vectors, a, w, h, thickness, v, n);
					break;

				case ArrowCaps.End:
					vectors.Add(a);
					AddCap(vectors, b, w, h, thickness, -v, -n);
					break;

				case ArrowCaps.Both:
					AddCap(vectors, a, w, h, thickness, v, n);
					AddCap(vectors, b, w, h, thickness, -v, -n);
					break;

				default:
					throw new ArgumentException();
			}

			return GetGeometry(vectors);
		}

		static void AddCap(ICollection<Vector> vectors, Vector sharp, double w, double h, double thickness, Vector v, Vector n) {
			sharp += v * thickness;
			var pivot = sharp + v*w;
			
			vectors.Add(pivot);
			vectors.Add(pivot + n*h);
			vectors.Add(sharp);
			vectors.Add(pivot - n*h);
			vectors.Add(pivot);
		}

		static Geometry GetGeometry(IEnumerable<Vector> vectors) {
			var geometry = new StreamGeometry();
			using (var context = geometry.Open()) {
				var first = true;
				foreach (var point in vectors.MapLazy(vector => vector.ToPoint())) {
					if (first) {
						context.BeginFigure(point, true, false);
						first = false;
					}
					else {
						context.LineTo(point, true, false);
					}
				}
			}

			return geometry;
		}
	}
}
